Skip to content
字数
832 字
阅读时间
4 分钟

背景

在接触微信小程序的过程中有个概念被反复强调,shadow tree ,现在统一归纳下其知识点

概述

——shadow 直译是 " 影子 " 的意思,shadow tree 则可以理解为隐藏的树

一个 DOM 元素通常包含两类 DOM 子树

  • Light tree:一般的 DOM 树,由 HTML 子元素组成
  • Shadow tree:一个隐藏的 DOM 子树,不在 HTML 中反应

如果一个元素同时拥有以上两种 DOM 子树,那么浏览器只渲染 shadow tree

示例

html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<script>
    customElements.define('shadow-test', class extends HTMLElement {
      connectedCallback() {
        const shadow = this.attachShadow({mode: 'open'});
        shadow.innerHTML = "这是Shadow DOM元素"
        const div = document.createElement("div")
        div.innerHTML = "这是Light DOM元素"
        this.append(div)
      }
    });
    </script>
<body>
    <shadow-test></shadow-test> 
</body>
</html>

显示如图:

结构组成

Shadow DOM 允许将隐藏的 DOM 树附加到常规的 DOM 树中——它以 shadow root 节点为起始根节点,在这个根节点的下方,可以是任意元素,和普通的 DOM 元素一样

Shadow host:一个常规 DOM 节点,Shadow DOM 会被附加到这个节点上。
Shadow tree:Shadow DOM 内部的 DOM 树。
Shadow boundary:Shadow DOM 结束的地方,也是常规 DOM 开始的地方。
Shadow root: Shadow tree 的根节点

创建一个 shadow dom

调用 elem.attachShadow({mode: "opne"/"closed"}) 来创建一个 shadow root

  • 每个元素中只能有一个 shadow root
  • elem 必须是自定义元素,或者是以下元素中其中一个:article、aside、blockquote、body、div、footer、h1、h1、h2、h3、h4、h5、h6、header、main、nav、p、section 和 span。其他元素则不能容纳 shadow tree
  • mode 选择的值为 open 或者 closed

区别于一般 dom

shadow dom 会和主文档分开

  • Shadow DOM 元素对于 light DOM 中的 querySelector 不可见
  • Shadow DOM 有自己的样式。外部样式规则在 shadow DOM 中不产生作用
  • 获取 shadow tree 内部的元素,我们可以从树的内部查询
  • 拥有自己的 id 空间

访问 shadow dom 样式

通过伪元素来访问到 shadow 的内部元素并改变其样式

CSS
input[type=range]::-webkit-slider-runnable-track {
  -webkit-appearance: none;
  background-color: chocolate;
}

修改 shadow dom 样式

  • 可以使用 elem.style 设置样式
  • 也可以创建 <style> 元素为 shadow tree 添加全局样式
  • 还可以通过创建 <link> 标签引入外部样式
js
// 将外部引用的样式添加到 Shadow DOM 上
const linkElem = document.createElement('link');
linkElem.setAttribute('rel', 'stylesheet');
linkElem.setAttribute('href', 'style.css');

// 将所创建的元素添加到 Shadow DOM 上

shadow.appendChild(linkElem);

作用

作用:增强组件内聚性(封装性

An important aspect of web components is encapsulation — being able to keep the markup structure, style, and behavior hidden and separate from other code on the page so that different parts do not clash, and the code can be kept nice and clean.

  • Web 组件的一个重要方面是封装 —— 能够将标记结构、样式和行为隐藏起来,并与页面上的其他代码分开,这样不同的部分就不会发生冲突,代码也能保持整洁

通常使用 Shadow dom 是在自定义元素中使用,目的是为了隐藏组件内部结构和有效样式

参考

究竟什么是Shadow DOM

认识Shadow DOM

Using shadow DOM - Web Components | MDN

贡献者

The avatar of contributor named as jiechen jiechen

页面历史

撰写